import os
import json
import pymysql
import psycopg2
from psycopg2 import sql
from pymysql.cursors import DictCursor
import importlib.util
from collections import OrderedDict

from conf.base_conf import BaseConf

# 全局字典：值类型到UI控件类型的映射
valueDataType_conf = {
    "TEXT": "textbox",
    "CMDB_ITEM": "combobox",
    "DICTIONARY": "combobox",
    "COORDINATE": "textbox",
    "MONTH": "combobox",
    "DATE": "textbox",
    "BINARY": "textbox"
}

# 全局字典：MySQL类型到值类型的映射
mysql_type_map = {
    'char': 'TEXT',
    'varchar': 'TEXT',
    'text': 'TEXT',
    'tinytext': 'TEXT',
    'mediumtext': 'TEXT',
    'longtext': 'TEXT',
    'enum': 'TEXT',
    'set': 'TEXT',
    'int': 'TEXT',
    'integer': 'TEXT',
    'bigint': 'TEXT',
    'smallint': 'TEXT',
    'tinyint': 'TEXT',
    'mediumint': 'TEXT',
    'float': 'TEXT',
    'double': 'TEXT',
    'decimal': 'TEXT',
    'numeric': 'TEXT',
    'date': 'DATE',
    'datetime': 'DATE',
    'timestamp': 'DATE',
    'time': 'DATE',
    'year': 'DATE',
    'datepicker': 'DATE',
    'blob': 'BINARY',
    'tinyblob': 'BINARY',
    'mediumblob': 'BINARY',
    'longblob': 'BINARY'
}

# 基础模板定义
BASIC_TEMPLATES = {
    "add": {
        "loc_sure": {
            "page_role": "dialog",
            "page_title": "新 增",
            "loc_role": "button",
            "loc_name": "确 定"
        },
        "loc_cancel": {
            "page_role": "dialog",
            "page_title": "新 增",
            "loc_role": "button",
            "loc_name": "取 消"
        },
        "loc_close": {
            "page_role": "dialog",
            "page_title": "新 增",
            "loc_role": "button",
            "loc_name": "关闭此对话框"
        }
    },
    "edit": {
        "loc_sure": {
            "page_role": "dialog",
            "page_title": "编 辑",
            "loc_role": "button",
            "loc_name": "确 定"
        },
        "loc_cancel": {
            "page_role": "dialog",
            "page_title": "编 辑",
            "loc_role": "button",
            "loc_name": "取 消"
        },
        "loc_close": {
            "page_role": "dialog",
            "page_title": "编 辑",
            "loc_role": "button",
            "loc_name": "关闭此对话框"
        }
    },
    "detail": {
        "loc_close": {
            "page_role": "dialog",
            "page_title": "查 看",
            "loc_role": "button",
            "loc_name": "关闭此对话框"
        }
    },
    "list": {
        "loc_checkbox": {
            "loc_role": "checkbox",
            "loc_name": ""
        },
        "loc_add": {
            "loc_role": "button",
            "loc_name": "新 增"
        },
        "loc_delete": {
            "loc_role": "button",
            "loc_name": "删 除"
        },
        "loc_search": {
            "loc_role": "button",
            "loc_name": "查 询"
        },
        "loc_reset": {
            "loc_role": "button",
            "loc_name": "重 置"
        },
        "loc_detail": {
            "loc_role": "button",
            "loc_name": "查 看"
        },
        "loc_edit": {
            "loc_role": "button",
            "loc_name": "编 辑"
        },
        "loc_sure": {
            "page_role": "dialog",
            "page_title": "提示",
            "loc_role": "button",
            "loc_name": "确定"
        },
        "loc_cancel": {
            "page_role": "dialog",
            "page_title": "提示",
            "loc_role": "button",
            "loc_name": "取消"
        },
        "loc_close": {
            "page_role": "dialog",
            "page_title": "提示",
            "loc_role": "button",
            "loc_name": "关闭此对话框"
        }
    }
}


def process_cmdb_data(cmdb_type, attrs_py):
    """处理CMDB数据并生成属性类文件"""
    try:
        conn = psycopg2.connect(
            host=BaseConf.CMDB_HOST,
            port=BaseConf.CMDB_PORT,
            database=BaseConf.CMDB_DATABASE,
            user=BaseConf.CMDB_USER,
            password=BaseConf.CMDB_PASSWORD
        )

        with conn.cursor() as cursor:
            query = sql.SQL('SELECT attrs FROM "public"."dw_d_cmdb_ct" WHERE "key" = %s')
            cursor.execute(query, (cmdb_type,))
            result = cursor.fetchone()

            if not result:
                print(f"未找到key为{cmdb_type}的记录")
                return

            attrs = json.loads(result[0])
            class_name = os.path.splitext(os.path.basename(attrs_py))[0]
            class_lines = [
                "#! /usr/bin/env python",
                "# -*- coding: utf-8 -*-",
                "",
                f"class {class_name}:",
                '    """',
                f"    {cmdb_type}的属性类",
                '    """',
                "",
                "    attributes = {"
            ]

            for key, attr in attrs.items():
                attr_str = json.dumps(attr, indent=8, ensure_ascii=False)
                attr_str = attr_str.replace(': true', ': True').replace(': false', ': False')
                class_lines.append(f'        "{key}": {attr_str},')

            class_lines.append("    }")
            class_lines.append("")

            class_content = "\n".join(class_lines)
            os.makedirs(os.path.dirname(attrs_py), exist_ok=True)

            with open(attrs_py, 'w', encoding='utf-8') as f:
                f.write(class_content)
            print(f"成功生成属性类文件: {attrs_py}")

    except Exception as e:
        print(f"处理CMDB数据时发生错误: {e}")
    finally:
        if 'conn' in locals():
            conn.close()


def process_mysql_data(sql_database, sql_table, attrs_py):
    """处理MySQL表结构并生成属性类文件"""
    try:
        conn = pymysql.connect(
            host=BaseConf.MYSQL_HOST,
            user=BaseConf.MYSQL_USER,
            password=BaseConf.MYSQL_PASSWORD,
            port=BaseConf.MYSQL_PORT,
        )

        with conn.cursor(DictCursor) as cursor:
            cursor.execute(
                "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH "
                "FROM information_schema.COLUMNS "
                "WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s",
                (sql_database, sql_table)
            )
            columns = cursor.fetchall()

            if not columns:
                print(f"未找到数据库{sql_database}中的表{sql_table}")
                return

            formatted_attrs = {}
            for col in columns:
                column_name = col['COLUMN_NAME']
                data_type = col['DATA_TYPE'].lower()
                comment = col['COLUMN_COMMENT'] or column_name
                is_nullable = col['IS_NULLABLE'] == 'YES'
                length = col['CHARACTER_MAXIMUM_LENGTH'] or 0

                value_data_type = mysql_type_map.get(data_type, 'TEXT')

                formatted_attrs[column_name] = {
                    "name": comment,
                    "valueDataType": value_data_type,
                    "require": not is_nullable,
                    "length": length,
                    "originalType": data_type
                }

            class_name = os.path.splitext(os.path.basename(attrs_py))[0]
            class_lines = [
                "#! /usr/bin/env python",
                "# -*- coding: utf-8 -*-",
                "",
                f"class {class_name}:",
                '    """',
                f"    {sql_table}表的属性类",
                '    """',
                "",
                "    attributes = {"
            ]

            for key, attr in formatted_attrs.items():
                attr_str = json.dumps(attr, indent=8, ensure_ascii=False)
                attr_str = attr_str.replace(': true', ': True').replace(': false', ': False')
                class_lines.append(f'        "{key}": {attr_str},')

            class_lines.append("    }")
            class_lines.append("")

            class_content = "\n".join(class_lines)
            os.makedirs(os.path.dirname(attrs_py), exist_ok=True)

            with open(attrs_py, 'w', encoding='utf-8') as f:
                f.write(class_content)
            print(f"成功生成属性类文件: {attrs_py}")

    except Exception as e:
        print(f"处理MySQL数据时发生错误: {e}")
    finally:
        if 'conn' in locals():
            conn.close()


def generate_locator(attr, page_type):
    """根据属性配置生成定位器字典"""
    control_type = valueDataType_conf.get(attr["valueDataType"], "textbox")
    name = attr["name"] + ":"

    if page_type in ["add", "edit"]:
        if attr.get("require", False):
            name = f'* {name}'
        page_title = "新 增" if page_type == "add" else "编 辑"
        return {
            "page_role": "dialog",
            "page_title": page_title,
            "loc_role": control_type,
            "loc_name": name
        }
    elif page_type == "detail":
        return {
            "page_role": "dialog",
            "page_title": "查 看",
            "loc_role": control_type,
            "loc_name": name
        }
    else:  # list
        return {
            "loc_role": "columnheader",
            "loc_name": name
        }


def process_attributes_loc(attrs_py, loc_py):
    """根据属性配置生成定位器字典"""
    loc_type = ["list", "add", "edit", "detail"]

    try:
        # 动态导入属性类
        module_name = os.path.splitext(os.path.basename(attrs_py))[0]
        spec = importlib.util.spec_from_file_location(module_name, attrs_py)
        module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(module)
        cls = getattr(module, module_name)
        attributes = cls.attributes

        for type in loc_type:
            # 创建有序字典保持字段顺序
            loc_dict = OrderedDict()

            # 添加基础模板
            for key, value in BASIC_TEMPLATES.get(type, {}).items():
                loc_dict[key] = value

            # 按order排序属性
            sorted_attrs = sorted(
                [(key, attr) for key, attr in attributes.items()],
                key=lambda x: x[1].get("order", 0)
            )

            # 添加属性字段
            for key, attr in sorted_attrs:
                loc_key = "loc_" + key
                loc_dict[loc_key] = generate_locator(attr, type)

            # 生成类文件
            class_name = "Loc" + os.path.splitext(os.path.basename(loc_py))[0].capitalize() + type.capitalize()
            file_name = "loc_" + os.path.splitext(os.path.basename(loc_py))[0] + "_" + type + ".py"
            new_loc_py = os.path.join(os.path.dirname(loc_py), file_name)

            # 创建类内容
            class_lines = [
                "from common.locate_by import By",
                "",
                f"class {class_name}:",
                ""
            ]

            # 添加定位器属性
            for loc_key, loc_info in loc_dict.items():
                class_lines.append(f"    {loc_key} = {{")
                for k, v in loc_info.items():
                    # 特殊处理角色字段
                    if k in ["page_role", "loc_role"] and v:
                        class_lines.append(f'        "{k}": By.{v},')
                    else:
                        class_lines.append(f'        "{k}": "{v}",')
                class_lines.append("    }")
                class_lines.append("")

            class_content = "\n".join(class_lines)

            # 确保目录存在
            os.makedirs(os.path.dirname(new_loc_py), exist_ok=True)

            with open(new_loc_py, 'w', encoding='utf-8') as f:
                f.write(class_content)
            print(f"成功生成定位器文件: {new_loc_py}")

    except Exception as e:
        print(f"生成定位器时发生错误: {e}")